﻿using Iworld.Basis.Help;
using Iworld.Basis.Manager;
using Iworld.Basis.Model;
using Iworld.Game.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;

namespace Iworld.Game.Manager
{
    /// <summary>
    /// 游戏管理器
    /// </summary>
    [RegisterToManagerService]
    public class GameManager : ManagerBase<IModelToDbContextOfGame, GameManager.Actions, GameChapter>
    {
        public GameManager(IModelToDbContextOfGame db)
            : base(db)
        {

        }

        /// <summary>
        /// 当前运行时服务器标识符
        /// </summary>
        static string Tk = Guid.NewGuid().ToString();

        /// <summary>
        /// 当前运行时牌轮号
        /// </summary>
        static int CurrentGameChapterNum = 1;

        /// <summary>
        /// 设置和运行时有关的信息
        /// </summary>
        /// <param name="game"></param>
        public static void SetRuntime(GameChapter game)
        {
            game.Tk = GameManager.Tk;
            game.ChapterNumber = CurrentGameChapterNum;
            CurrentGameChapterNum++;
        }

        /// <summary>
        /// 获取当前运行时的标识符
        /// </summary>
        /// <returns></returns>
        public static string GetCurrentTk()
        {
            return GameManager.Tk;
        }

        /// <summary>
        /// 获得当前的限红分数设置
        /// </summary>
        /// <returns></returns>
        public static double GetCurrentLimitRed()
        {
            return limit;
        }

        /// <summary>
        /// 当前的限红分数
        /// </summary>
        static double limit = -1;

        /// <summary>
        /// 刷新当前的限红分数,每当牌局结束的时候刷新
        /// </summary>
        /// <param name="db"></param>
        static void RefreshLimit(IModelToDbContextOfGame db)
        {
            SettingOfGame sg = new SettingOfGame(db);
            limit = sg.LimitRedGolds;
        }

        /// <summary>
        /// 是否在处理
        /// </summary>
        static bool isUpdating = false;

        /// <summary>
        /// 定时检测更新牌轮
        /// </summary>
        /// <param name="info"></param>
        [Listen(typeof(TimelineManager),TimelineManager.Actions.SparkEachSecond,ExecutionOrder.After)]
        public static void UpdateGameChapter(InfoOfSendOnManagerService info)
        {
               if (isUpdating) return;
                try
                {
                        isUpdating = true;
                        TimelineManager.SparkArgs args = (TimelineManager.SparkArgs)info.Args;
                        using(IModelToDbContextOfGame db = (IModelToDbContextOfGame)args.GetDb())
                        {
                          //  using(TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
                          //  {
                                //Logger.Debug("定时检测更新牌轮......" + args.Now);

                                ///是否为刚刚启动服务器,还未有当前运行环境的牌轮
                                bool isRuntimeFrist = !db.GameChapters.Any(x => x.Tk == GameManager.Tk);
                                SettingOfGame sg = new SettingOfGame(db);
                                if(isRuntimeFrist)
                                {//如果是刚启动服务器,则生成2个牌轮
                                    GameManager gm = new GameManager(db);
                                    Logger.Debug("检测到刚刚启动服务器,正在生成2个牌轮......");
                                    //把以前未完成的牌轮设置为终止
                                    db.GameChapters.Where(x => (x.Tk != GameManager.Tk) &&
                                        ( x.Status == GameChapterStatus.正在开奖 || x.Status == GameChapterStatus.从未开奖))
                                        .ToList().ForEach(x=>x.Status = GameChapterStatus.终止);
                                    gm.Create(new PackageForCreateGameChapter(){ ActiveTime = args.Now.AddSeconds(sg.EachChapterTimeSpan)});
                                    gm.Create(new PackageForCreateGameChapter());
                                    RefreshLimit(db);
                                  //  ts.Complete();
                                    return;
                                }
                                ///当前是否有正在开奖的牌轮
                                GameChapter game = db.GameChapters.FirstOrDefault(x => x.Status == GameChapterStatus.正在开奖 &&
                                    x.Tk == GameManager.Tk);
                                if (game == null)
                                {//如果没有正在开奖的牌轮,则查询存在激活时间的牌轮

                                    game = db.GameChapters.FirstOrDefault(x => x.Status == GameChapterStatus.从未开奖 && 
                                        x.ActiveTime != null && ((DateTime)x.ActiveTime) <= args.Now
                                        && x.Tk == GameManager.Tk );
                                    if (game != null)
                                    {
                                        game.Status = GameChapterStatus.正在开奖;
                                        game.NextRoundNumber = 1;
                                        game.NextRoundLotteryTime = args.Now.AddSeconds(sg.EachRoundTimeSpan);
                                        Logger.Debug("正在激活牌轮,牌轮号:" + game.ChapterNumber + ",下期开奖时间:" 
                                            + game.NextRoundLotteryTime);
                                        db.SaveChanges();
                                    }
                                    //Logger.Debug("未找到正在开奖的牌轮......");
                                }
                                if (game == null)
                                {
                                   // Logger.Debug("当前没有牌轮正在开奖,也没到牌轮激活时间,中场休息ing......");
                                    return;
                                }
                                ///下局需要开奖的牌局
                                GameRound next = game.GameRounds.Find(x => x.RoundNum == game.NextRoundNumber);
                              ///如果到了封单时间触发封单动作
                                if (!next.IsClosureSingle &&
                                     ((DateTime)game.NextRoundLotteryTime).AddSeconds(-sg.ClosureSingleTime) <= args.Now)
                                {
                                    GameManager gm = new GameManager(db);
                                    gm.OnExecuting(Actions.ClosureSingle, game, next);
                                    next.IsClosureSingle = true;
                                    gm.OnExecuted(Actions.ClosureSingle, game, next);
                                    db.SaveChanges();
                                }
                                //如果到了下期开奖时间
                                if (game.NextRoundLotteryTime <= args.Now)
                                {
                                    ///更新限红
                                    RefreshLimit(db);
                                    GameManager gm = new GameManager(db);
                                    gm.OnExecuting(Actions.Lottery, game, next);
                                    next.LotteryTime = args.Now;
                                    next.IsLottery = true;
                                    game.CurrentRoundNumber = next.RoundNum;
                                    Logger.Debug("["+args.Now+"] 正在开奖......牌轮号ID:" + game.ChapterNumber + ",牌局号" + next.RoundNum+
                                        ",结果:" + next.PokerColor + next.PokerNumber);
                                    if (next.RoundNum >= game.GameRounds.Count)//如果已经到最后一局
                                    {
                                        gm.OnExecuting(Actions.ChapterEnd, game, args.Now);
                                        gm.OnExecuted(Actions.ChapterEnd, game, args.Now);
                                    }else
                                    {
                                        game.NextRoundLotteryTime = args.Now.AddSeconds(sg.EachRoundTimeSpan);
                                        game.NextRoundNumber = (next.RoundNum+1);
                                    }
                                    gm.OnExecuted(Actions.Lottery, game, next);
                                    db.SaveChanges();
                                }
                               // ts.Complete();
                       //  }
                        }
            
                }catch(Exception ex)
                {
                    Logger.Debug("UpdateGameChapter方法出错了:" + ex.Message);
                }
                finally
                {
                    isUpdating = false;
                }
             
        }

        /// <summary>
        /// 监听牌轮结束
        /// </summary>
        /// <param name="info"></param>
        [Listen(typeof(GameManager), GameManager.Actions.ChapterEnd, ExecutionOrder.After)]
        public static void ListenChapterEnd(InfoOfSendOnManagerService info)
        {
            GameChapter game = (GameChapter)info.Model;
            DateTime now = (DateTime)info.Args;
            game.NextRoundLotteryTime = null;
            game.NextRoundNumber = null;
            game.EndTime = now;
            game.Status = GameChapterStatus.开奖结束;
            IModelToDbContextOfGame db = (IModelToDbContextOfGame)info.Db;
            SettingOfGame sg = new SettingOfGame(db);
            //激活另一个牌轮
            GameChapter next = db.GameChapters.FirstOrDefault(x => x.Status == GameChapterStatus.从未开奖 &&
                x.Tk == GameManager.Tk && x.ActiveTime == null);
            if(next != null)
            {
                next.ActiveTime = now.AddSeconds(sg.EachChapterTimeSpan);
            }
            //每当一个牌轮结束时创建一个新的牌轮
            GameManager gm = new GameManager(db);
            gm.Create(new PackageForCreateGameChapter());
            Logger.Debug("牌轮结束,牌轮号:"+game.ChapterNumber);
        }


        public enum Actions
        {
            /// <summary>
            /// 创建牌轮
            /// </summary>
            Create,
            Update,
            Remove,
            /// <summary>
            /// 每次牌轮结束
            /// </summary>
            ChapterEnd,
            /// <summary>
            /// 开奖
            /// </summary>
            Lottery,
            /// <summary>
            /// 激活牌轮
            /// </summary>
            ChapterActive,
            /// <summary>
            /// 重新启动服务器后第一次生成牌轮
            /// </summary>
            RuntimeFirstCreate,
            /// <summary>
            /// 封单
            /// </summary>
            ClosureSingle
        }

       
        /// <summary>
        /// 生成牌轮的封包
        /// </summary>
        class PackageForCreateGameChapter : IPackageForCreateModel<IModelToDbContextOfGame,GameChapter>
        {

            public void CheckData(IModelToDbContextOfGame db)
            {
                
            }

            public DateTime? ActiveTime { set; get; }

            public GameChapter GetModel(IModelToDbContextOfGame db)
            {
                SettingOfGame sg = new SettingOfGame(db);
                int totalRound = sg.EachChapterRoundCount;
                if (totalRound <= 0)
                {
                    throw new Exception("局数不能小于0");
                }
                GameChapter game = new GameChapter()
                {
                    TotalRoundCount = totalRound,
                    Status = GameChapterStatus.从未开奖
                };
                game.GameRounds = new List<GameRound>();
                for (int k = 1; k <= totalRound; k++)
                {
                    GameRound gr = new GameRound() { RoundNum = k, GameChapter = game };
                    Random ram = new Random(k);
                    int i = ram.Next(0, 100);
                    if (i < 20)
                    {
                        gr.PokerColor = PokerColor.黑桃;
                    }
                    else if (i < 60)
                    {
                        gr.PokerColor = PokerColor.红桃;
                    }
                    else if (i < 80)
                    {
                        gr.PokerColor = PokerColor.梅花;
                    }
                    else if (i < 95)
                    {
                        gr.PokerColor = PokerColor.方块;
                    }
                    else
                    {
                        gr.PokerColor = PokerColor.王;
                    }
                    gr.PokerNumber = (PokerNumber)(i % 13 + 1);
                    game.GameRounds.Add(gr);
                }
                if (ActiveTime != null)
                {
                    game.ActiveTime = this.ActiveTime;
                }
                GameManager.SetRuntime(game);
                return game;
            }
        }
    }
}
